package com.yiyuan.app.dao;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guaike.core.mybatis.plugins.BaseDAO;
import com.yiyuan.app.entity.enums.RoomTypeEnum;
import com.yiyuan.app.entity.po.GRecordGamePO;
import com.yiyuan.app.mapper.GRecordGameExtMapper;
import com.yiyuan.app.mapper.GRecordGameMapper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
@AllArgsConstructor
public class GRecordGameDAO extends BaseDAO<GRecordGameMapper, GRecordGamePO> {

    private final GRecordGameExtMapper gRecordGameExtMapper;

    public GRecordGamePO findByIdLock(Long id) {
        return gRecordGameExtMapper.findByIdLock(id);
    }

    public Page<GRecordGamePO> findHistoryPage(Long userId, Integer pageIndex, Integer pageSize) {
        LambdaQueryWrapper<GRecordGamePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GRecordGamePO::getUserId, userId);
        queryWrapper.lt(GRecordGamePO::getEndTime, LocalDateTime.now());
        queryWrapper.orderByDesc(GRecordGamePO::getId);
        return getBaseMapper().selectPage(new Page<>(pageIndex, pageSize), queryWrapper);
    }

    public GRecordGamePO findUserPlaying(Long userId, Long roomId, String positionNo) {
        LambdaQueryWrapper<GRecordGamePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GRecordGamePO::getUserId, userId);
        queryWrapper.and(wrapper -> wrapper.isNull(GRecordGamePO::getEndTime).or().ge(GRecordGamePO::getEndTime, LocalDateTime.now()));
        queryWrapper.eq(GRecordGamePO::getRoomId, roomId);
        queryWrapper.eq(GRecordGamePO::getPositionNo, positionNo);
        queryWrapper.orderByDesc(GRecordGamePO::getId);
        queryWrapper.last("limit 0,1");
        return getBaseMapper().selectOne(queryWrapper);
    }

    public GRecordGamePO findRoomPlaying(Long roomId, String positionNo) {
        LambdaQueryWrapper<GRecordGamePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.isNull(GRecordGamePO::getEndTime).or().ge(GRecordGamePO::getEndTime, LocalDateTime.now()));
        queryWrapper.eq(GRecordGamePO::getRoomId, roomId);
        queryWrapper.eq(GRecordGamePO::getPositionNo, positionNo);
        queryWrapper.orderByDesc(GRecordGamePO::getId);
        queryWrapper.last("limit 0,1");
        return getBaseMapper().selectOne(queryWrapper);
    }

    public GRecordGamePO findRoomLatestHistory(Long roomId, String positionNo) {
        LambdaQueryWrapper<GRecordGamePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.lt(GRecordGamePO::getEndTime, LocalDateTime.now());
        queryWrapper.eq(GRecordGamePO::getRoomId, roomId);
        queryWrapper.eq(GRecordGamePO::getPositionNo, positionNo);
        queryWrapper.orderByDesc(GRecordGamePO::getId);
        queryWrapper.last("limit 0,1");
        return getBaseMapper().selectOne(queryWrapper);
    }

    public List<GRecordGamePO> findRoomPlaying(Long roomId) {
        LambdaQueryWrapper<GRecordGamePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.isNull(GRecordGamePO::getEndTime).or().ge(GRecordGamePO::getEndTime, LocalDateTime.now()));
        queryWrapper.eq(GRecordGamePO::getRoomId, roomId);
        return getBaseMapper().selectList(queryWrapper);
    }

    public long countRoomPlaying(Long roomId) {
        LambdaQueryWrapper<GRecordGamePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.isNull(GRecordGamePO::getEndTime).or().ge(GRecordGamePO::getEndTime, LocalDateTime.now()));
        queryWrapper.eq(GRecordGamePO::getRoomId, roomId);
        return getBaseMapper().selectCount(queryWrapper);
    }

    public int updateData(Long id, Integer usePinecone, Integer getPineNut, LocalDateTime finallyCoinTime) {
        return gRecordGameExtMapper.updateData(id, usePinecone, getPineNut, finallyCoinTime);
    }

    public int updatePushCoinsEndTime(Long id) {
        return gRecordGameExtMapper.updatePushCoinsEndTime(id);
    }

    public List<GRecordGamePO> findGamingList(Long roomId, Long userId) {
        LambdaQueryWrapper<GRecordGamePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GRecordGamePO::getRoomId, roomId);
        queryWrapper.eq(GRecordGamePO::getUserId, userId);
        queryWrapper.and(wrapper -> wrapper.isNull(GRecordGamePO::getEndTime).or().gt(GRecordGamePO::getEndTime, LocalDateTime.now()));
        queryWrapper.orderByDesc(GRecordGamePO::getId);
        return getBaseMapper().selectList(queryWrapper);
    }

    public GRecordGamePO findLatestGaming(Long roomId, Long userId) {
        LambdaQueryWrapper<GRecordGamePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GRecordGamePO::getRoomId, roomId);
        queryWrapper.eq(GRecordGamePO::getUserId, userId);
        queryWrapper.and(wrapper -> wrapper.isNull(GRecordGamePO::getEndTime).or().gt(GRecordGamePO::getEndTime, LocalDateTime.now()));
        queryWrapper.orderByDesc(GRecordGamePO::getId);
        queryWrapper.last("limit 0,1");
        return getBaseMapper().selectOne(queryWrapper);
    }

    public GRecordGamePO findPushCoinsLatestGaming(Long roomId, String positionNo) {
        LambdaQueryWrapper<GRecordGamePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.isNull(GRecordGamePO::getEndTime).or().ge(GRecordGamePO::getEndTime, LocalDateTime.now()));
        queryWrapper.eq(GRecordGamePO::getRoomId, roomId);
        queryWrapper.eq(GRecordGamePO::getPositionNo, positionNo);
        queryWrapper.orderByDesc(GRecordGamePO::getId);
        queryWrapper.eq(GRecordGamePO::getRoomType, RoomTypeEnum.push_coins.getCode());
        queryWrapper.last("limit 0,1");
        return getBaseMapper().selectOne(queryWrapper);
    }


    public int updateGameEnd(Long id) {
        LambdaUpdateWrapper<GRecordGamePO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(GRecordGamePO::getEndTime, LocalDateTime.now());
        updateWrapper.eq(GRecordGamePO::getId, id);
        return getBaseMapper().update(new GRecordGamePO(), updateWrapper);
    }

    public int updateOccupyGameEnd(Long id) {
        LambdaUpdateWrapper<GRecordGamePO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(GRecordGamePO::getEndTime, LocalDateTime.now().plusMinutes(3));
        updateWrapper.eq(GRecordGamePO::getId, id);
        return getBaseMapper().update(new GRecordGamePO(), updateWrapper);
    }

    public int updateOccupyGameEndNew(Long id) {
        LambdaUpdateWrapper<GRecordGamePO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(GRecordGamePO::getEndTime, LocalDateTime.now());
        updateWrapper.eq(GRecordGamePO::getId, id);
        return getBaseMapper().update(new GRecordGamePO(), updateWrapper);
    }
}
